package com.wiselink.fastbox;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import lombok.Getter;
import lombok.ToString;
import okhttp3.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

/**
 * FastBox API
 */
public abstract class FastBoxBaseAPI {
    public static final Logger log = LoggerFactory.getLogger(FastBoxBaseAPI.class);
    private static boolean inited = false;
    private static Env env;
    private static final String TEST_URL = "http://dhub-api.cafe24test.com";
    private static final String QA_URL = "https://dhub-api-qa.cafe24.com";
    private static final String PROD_URL = "https://dhub-api.cafe24.com";
    public static final MediaType mediaType = MediaType.parse("application/json; charset=utf-8");
    public static ShopInfo shop;
    private static OkHttpClient CLIENT;

    @ToString
    @Getter
    public static class ShopInfo {
        /**
         * 商城ID
         * 例如：bahetest
         */
        public String mallId;
        /**
         * 店铺名称
         * 例如：바흐테스트
         */
        public String shopName;
        /**
         * 卖家名称
         * 例如：바흐
         */
        public String sellerName;

        /**
         * 店铺地址（英文）
         */
        public String addressEng;

        public ShopInfo(String mallId, String shopName, String sellerName, String addressEng) {
            this.mallId = mallId;
            this.shopName = shopName;
            this.sellerName = sellerName;
            this.addressEng = addressEng;
        }
    }

    public FastBoxBaseAPI() {
        if (!inited) {
            throw new RuntimeException("请先初始化 FastBoxBaseAPI");
        }
    }

    public static void init(String e, String consumerKey, String token, ShopInfo shopInfo) {
        env = Env.valueOf(e);
        log.error("FastBoxBaseAPI 初始化, env: {}, {}", e, env.getUrl());
        CLIENT = new OkHttpClient.Builder()
                .addInterceptor(chain -> {
                    Request original = chain.request();
                    Request request = original.newBuilder()
                            .header("consumerKey", consumerKey)
                            .header("Authorization", "Bearer " + token)
                            .method(original.method(), original.body())
                            .build();
                    return chain.proceed(request);
                })
                // 连接超时
                .connectTimeout(30, TimeUnit.SECONDS)
                // 读超时
                .readTimeout(30, TimeUnit.SECONDS)
                // 写超时
                .writeTimeout(30, TimeUnit.SECONDS)
                // 连接池配置（默认 keep-alive）
                .connectionPool(new ConnectionPool(5, 5, TimeUnit.MINUTES))
                // 自动重试
                .retryOnConnectionFailure(true)
                .build();
        shop = shopInfo;
        inited = true;
        log.error("FastBoxBaseAPI 完成初始化");
    }

    public static OkHttpClient getClient() {
        return CLIENT;
    }

    @Getter
    public enum Env {
        TEST(TEST_URL),
        QA(QA_URL),
        PROD(PROD_URL);

        private final String url;

        Env(String url) {
            this.url = url;
        }

    }

    public abstract String getPath();

    public abstract Map<String, String> getRequestParam();

    public abstract String getRequestData();

    public abstract void processResponseResult(JSONObject jsonResult);

    public final void get() {
        // 通过params中的参数 拼接 url请求参数
        HttpUrl.Builder urlBuilder = HttpUrl.parse(env.getUrl() + getPath()).newBuilder();
        urlBuilder.addQueryParameter("mall_id", shop.getMallId());
        Map<String, String> params = getRequestParam();
        for (Map.Entry<String, String> entry : params.entrySet()) {
            urlBuilder.addQueryParameter(entry.getKey(), entry.getValue());
        }
        Request request = new Request.Builder()
                .url(urlBuilder.build())
                .get()
                .build();
        String result = getRequestResult(request);
        log.debug("get result: {}", result);
        processResponseResult(JSON.parseObject(result));
    }

    public final void post() {
        RequestBody body = getRequestBody(getRequestData());
        Request request = new Request.Builder()
                .url(env.getUrl() + getPath())
                .addHeader("Content-Type", "application/json")
                .post(body)
                .build();
        String result = getRequestResult(request);
        log.debug("post result: {}", result);
        processResponseResult(JSON.parseObject(result));
    }

    private RequestBody getRequestBody(String requestData) {
        Map<String, String> bodyMap = new HashMap<>();
        bodyMap.put("mall_id", shop.getMallId());
        bodyMap.put("request_data", requestData);
        return RequestBody.create(mediaType, JSON.toJSONString(bodyMap));
    }

    private String getRequestResult(Request request) {
        String result;
        try (Response response = getClient().newCall(request).execute()) {
            if (!response.isSuccessful()) {
                log.error("{} 请求失败! code:{} message:{}", request.url().uri().getPath(), response.code(), response.message());
                throw new RuntimeException("Unexpected code " + response);
            }
            result = Objects.requireNonNull(response.body()).string();
        } catch (IOException e) {
            log.error("{} 请求失败: {}", request.url().uri().getPath(), e.getMessage(), e);
            throw new RuntimeException(e);
        }
        return result;
    }

}
